package com.hsu.hsurpc.proxy;

import com.hsu.hsurpc.RpcApplication;
import com.hsu.hsurpc.config.RpcConfig;
import com.hsu.hsurpc.constant.RpcConstant;
import com.hsu.hsurpc.loadbalancer.LoadBalancer;
import com.hsu.hsurpc.loadbalancer.LoadBalancerFactory;
import com.hsu.hsurpc.model.RpcRequest;
import com.hsu.hsurpc.model.RpcResponse;
import com.hsu.hsurpc.model.ServiceMetaInfo;
import com.hsu.hsurpc.registry.Registry;
import com.hsu.hsurpc.registry.RegistryFactory;
import com.hsu.hsurpc.serializer.Serializer;
import com.hsu.hsurpc.serializer.SerializerFactory;
import com.hsu.hsurpc.server.tcp.VertxTcpClient;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 服务代理（JDK 动态代理）
 * 用于通过 JDK 动态代理发送 TCP 请求，调用远程服务
 * @Author Hsu琛君珩
 * @Date 2024-09-18 11:12
 * @Description
 * @Version: v1.0.0
 */
public class ServiceProxy implements InvocationHandler {

    /**
     * 代理方法调用
     * 该方法通过代理调用实现远程服务的调用流程，包括请求发送和响应接收。
     *
     * @param proxy 代理对象
     * @param method 被调用的方法
     * @param args 方法的参数
     * @return 返回远程服务调用的结果
     * @throws Throwable 如果调用过程中出现错误，抛出异常
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 指定序列化器
        final Serializer serializer = SerializerFactory.getInstance(RpcApplication.getRpcConfig().getSerializer());
        // 构造 RPC 请求对象
        String serviceName = method.getDeclaringClass().getName();
        RpcRequest rpcRequest = RpcRequest.builder()
                .serviceName(serviceName)                     // 设置服务名称
                .methodName(method.getName())                 // 设置方法名称
                .parameterTypes(method.getParameterTypes())   // 设置方法的参数类型数组
                .args(args)                                   // 设置方法参数
                .build();                                     // 构建 RpcRequest 对象
        try {
            // 获取全局 RPC 配置
            RpcConfig rpcConfig = RpcApplication.getRpcConfig();

            // 获取注册中心实例
            Registry registry = RegistryFactory.getInstance(rpcConfig.getRegistryConfig().getRegistry());
            // 服务发现，获取服务提供者信息
            ServiceMetaInfo serviceMetaInfo = new ServiceMetaInfo();
            serviceMetaInfo.setServiceName(serviceName);
            serviceMetaInfo.setServiceVersion(RpcConstant.DEFAULT_SERVICE_VERSION);
            // 获取服务提供者的元数据信息列表
            List<ServiceMetaInfo> serviceMetaInfoList = registry.serviceDiscovery(serviceMetaInfo.getServiceKey());
            // 如果未找到可用的服务地址，抛出异常
            if (serviceMetaInfoList == null || serviceMetaInfoList.isEmpty()) {
                System.out.println("没有找到服务：" + serviceMetaInfo.getServiceKey());
                throw new RuntimeException("暂无服务地址");
            }
            // 负载均衡
            LoadBalancer loadBalancer = LoadBalancerFactory.getInstance(rpcConfig.getLoadBalancer());
            // 构造负载均衡参数
            Map<String, Object> requestParams = new HashMap<>();
            requestParams.put("methodName", rpcRequest.getMethodName()); // 将方法名作为负载均衡参考参数
            // 使用负载均衡器选择一个服务节点
            ServiceMetaInfo selectedServiceMetaInfo = loadBalancer.select(requestParams, serviceMetaInfoList);
            // 通过 TCP 客户端发送请求并接收响应
            RpcResponse rpcResponse = VertxTcpClient.doRequest(rpcRequest, selectedServiceMetaInfo);
            // 返回响应中的数据
            return rpcResponse.getData();
        } catch (Exception e) {
            // 捕获异常并包装为 RuntimeException 抛出
            throw new RuntimeException("调用失败", e);
        }
    }
}
